package com.sky.service.impl;

import cn.hutool.core.collection.ListUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.constant.StatusConstant;
import com.sky.dto.DishDTO;
import com.sky.dto.DishPageQueryDTO;
import com.sky.entity.Dish;
import com.sky.entity.DishFlavor;
import com.sky.exception.DeletionNotAllowedException;
import com.sky.mapper.DishFlavorsMapper;
import com.sky.mapper.DishMapper;
import com.sky.mapper.SetmealDishMapper;
import com.sky.mapper.SetmealMapper;
import com.sky.result.PageResult;
import com.sky.service.DishService;
import com.sky.vo.DishVO;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;

/**
 * PROJECT_NAME: sky-take-out
 * NAME: DishServiceImpl
 * USER: zhang
 * DATE: 2023/5/16
 * DESCRIPTION :B端-菜品信息服务层接口实现类
 */
@Service
public class DishServiceImpl implements DishService {
    @Resource
    private DishMapper dishMapper;
    @Resource
    private DishFlavorsMapper dishFlavorsMapper;
    @Resource
    private SetmealDishMapper setmealDishMapper;

    /**
     * 新增菜品信息(包含菜品口味)
     *
     * @param dishDTO 用于接受菜品数据和菜品口味的Bean
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = "DISH_CACHE",allEntries = true)
    public void insertDish(DishDTO dishDTO) {
        //创建菜品信息对象（用于保存DTO原始数据）
        Dish dish = new Dish();
        BeanUtils.copyProperties(dishDTO, dish);
        //更改菜品的状态为启用状态
        dish.setStatus(StatusConstant.ENABLE);
        //调用持久层添加菜品基本信息
        dishMapper.insertDish(dish);
        //判断本次菜品数据是否包含菜品口味数据(包含则添加,不包含则不添加,如果不判断,则会出现SQL语句语法错误的问题)
        if (Objects.nonNull(dishDTO.getFlavors()) && dishDTO.getFlavors().size() > 0) {
            //处理DishDTO中的菜品口味信息 -> 默认将菜品口味对象封装好了(口味名称/口味数据)没有对应的菜品Id -> 从dish对象中获取
            Long dishId = dish.getId();
            //遍历菜品口味集合，给每一个菜品口味赋值一个菜品Id
            dishDTO.getFlavors().forEach(dishFlavor -> dishFlavor.setDishId(dishId));
            //将菜品口味集合交给菜品口味持久层进行批量添加
            dishFlavorsMapper.batchInsertDishFlavors(dishDTO.getFlavors());
        }

    }


    /**
     * 删除菜品信息
     *
     * @param ids 要删除菜品信息的集合
     */
    @CacheEvict(cacheNames = "DISH_CACHE",allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteDish(List<Long> ids) {
        //判断所有的要删除的菜品Id是否是启售状态 是:抛异常 没有:继续完成其他判断
        for (Long dishId : ids) {
            Dish dish = dishMapper.selectDishById(dishId);
            if (dish.getStatus().equals(StatusConstant.ENABLE)) {
                throw new DeletionNotAllowedException(MessageConstant.DISH_ON_SALE);
            }
        }
        //判断菜品套餐关联中是否存在与当前的Id有关联关系的数据 => 有:抛异常 没有:则完成删除
        Long count = setmealDishMapper.selectCountByDishIds(ids);
        if (count > 0) {
            throw new DeletionNotAllowedException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL);
        }
        //如果以上的操作完成后均未抛出异常(满足删除前提)
        dishMapper.deleteDish(ids);
        dishFlavorsMapper.batchDeleteDishFlavors(ids);

    }

    /**
     * 基于id查询菜品(包含口味)
     * @param dishId 要查询菜品的id
     * @return 全局通用返回信息Bean（完整的菜品信息）
     */
    @Override
    public DishVO selectDishVOById(Long dishId) {
        //调用持久层查询菜品信息
        Dish dish = dishMapper.selectDishById(dishId);
        //调用菜品口味持久层基于菜品Id查询菜品口味信息
        List<DishFlavor> dishFlavorList =  dishFlavorsMapper.selectDishFlavorByDishId(dishId);
        //封装一个DishVO返回
        DishVO dishVO = new DishVO();
        BeanUtils.copyProperties(dish, dishVO);
        dishVO.setFlavors(dishFlavorList);
        return dishVO;
    }

    /**
     * 更新菜品信息
     * @param dishDTO 更新后的菜品完整信息Bean(▲包含菜品Id)
     */
    @CacheEvict(cacheNames = "DISH_CACHE",allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateDish(DishDTO dishDTO) {
        //获取DishDTO中的菜品基本信息完成更新
        Dish dish = new Dish();
        BeanUtils.copyProperties(dishDTO,dish);
        dishMapper.updateDish(dish);

        //获取DishDTO的口味信息
        List<DishFlavor> dishFlavorList = dishDTO.getFlavors();

        //删除菜品口味表中所有当前DishId的口味信息
        dishFlavorsMapper.batchDeleteDishFlavors(ListUtil.of(dish.getId()));

        //如果口味信息集合不是Null并且长度大于0
        if (Objects.nonNull(dishFlavorList)&&dishFlavorList.size()>0){
            //遍历菜品口味，重新给每一个菜品口味赋值一个菜品Id
            dishFlavorList.forEach(dishFlavor->dishFlavor.setDishId(dish.getId()));
            //把新的口味信息进行添加
            dishFlavorsMapper.batchInsertDishFlavors(dishFlavorList);
        }

    }

    /**
     * 菜品的启售/停售
     */
    @CacheEvict(cacheNames = "DISH_CACHE",allEntries = true)
    @Override
    public void modifyStatus(Dish dish) {
        dishMapper.updateDish(dish);
    }

    /**
     * 基于分类Id查询菜品信息集合
     *
     * @param categoryId 菜品分类Id
     * @return 分类Id对应的菜品信息的集合
     */
    @Override
    public List<Dish> getDishByCategoryId(Long categoryId) {
       return dishMapper.selectDishByCategoryId(categoryId);
    }

    /**
     * 查询指定分类菜品和口味
     *
     * @param categoryId 菜品类别id
     * @return (包含菜品基本信息+口味信息)
     */
    @Override
    public List<DishVO> selectDishAndFlavorByCategoryId(Long categoryId) {
        //获取菜品信息的集合
        List<Dish> dishList = dishMapper.selectDishByCategoryId(categoryId);
        //声明一个结果返回集合
        List<DishVO> dishVOList = new ArrayList<DishVO>();
        //遍历dish基本信息集合，将菜品普通信息封装到dishVO中
        //根据dishId拿到口味信息
        for (Dish dish : dishList) {
            DishVO dishVO = new DishVO();
            //将dish基本信息封装到dishvo中
            BeanUtils.copyProperties(dish, dishVO);
            //将口味信息封装到dishVO中
            List<DishFlavor> dishFlavorList = dishFlavorsMapper.selectDishFlavorByDishId(dish.getId());
            dishVO.setFlavors(dishFlavorList);
            dishVOList.add(dishVO);
        }
        return dishVOList;

    }


    /**
     * 条件分页查询
     *
     * @param dishPageQueryDTO 分页查询的条件(页码/分页条数/菜品名称/分类Id/菜品状态)
     * @return 分页查询的结果Bean
     */
    @Override
    public PageResult selectByPage(DishPageQueryDTO dishPageQueryDTO) {
        PageHelper.startPage(dishPageQueryDTO.getPage(), dishPageQueryDTO.getPageSize());
        Page<DishVO> pageResults = dishMapper.selectByPage(dishPageQueryDTO);
        PageResult build = PageResult.builder().total(pageResults.getTotal()).records(pageResults.getResult()).build();
        return build;
    }


}
